#pragma once
#include <iostream>
#include <functional>
#include "common.hpp"
#include "macro.hpp"

namespace MyRpc
{
    // 消息类
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage() {}
        MType mtype() { return _mtype;}
        void setMType(const MType& mtype) { _mtype = mtype; }
        std::string& id() { return _id; }
        void setId(const std::string& id) { _id = id; }
        // 序列化 把数据序列化到字符串中 序列化为JSON格式的字符串
        virtual bool serialize(std::string& body) = 0;
        // 反序列化 把数据反序列化到 JSON::Value 中
        virtual bool unserialize(const std::string& body) = 0;
        virtual bool check() = 0;
    protected:
        std::string _id;
        MType _mtype;
    };

    // 消息缓冲区
    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;
        // 提供了读取缓冲区消息的接口
        // readableBytes 查看缓冲区有多少数据
        virtual size_t readableBytes() = 0;
        // peek 提供的接口是为了尝试查看数据是否够 不读取数据
        virtual int32_t peekInt32() = 0;
        // read 接口直接是读取数据 并且删除读取的数据 peek + retrieve 接口
        virtual int32_t readInt32() = 0;
        // retrieve 接口删除数据
        virtual void retrieveInt32() = 0;
        virtual std::string retrieveAsString(size_t len) = 0;
    };

    // 消息协议定制
    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        // 对消息进行判断是否可以处理
        virtual bool canProcessed(const BaseBuffer::ptr& buf) = 0;
        // 对消息进行序列化 把消息序列化为 LV格式的字符串
        virtual std::string serialize(const BaseMessage::ptr& msg) = 0;
        // 对消息进行处理的函数
        virtual bool onMessage(const BaseBuffer::ptr& buf, BaseMessage::ptr& msg) = 0;
    };

    // 连接管理
    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual bool send(const BaseMessage::ptr& msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    };

    // 服务端类
    using ConnectionCallBack = std::function<void(const BaseConnection::ptr&)>;
    using MessageCallBack = std::function<void(const BaseConnection::ptr&, const BaseMessage::ptr& msg)>;
    using CloseCallBack = std::function<void(const BaseConnection::ptr&)>;
    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        // 回调函数由用户自己设置
        virtual void setConnectionCallBack(const ConnectionCallBack& cb)
        {
            _conn_cb = cb;
        }
        virtual void setMessageCallBack(const MessageCallBack& cb)
        {
            _msg_cb = cb;
        }
        virtual void setCloseCallBack(const CloseCallBack& cb)
        {
            _close_cb = cb;
        }
        virtual void start() = 0;
    protected:
        ConnectionCallBack _conn_cb;
        MessageCallBack _msg_cb;
        CloseCallBack _close_cb;
    };

    // 客户端类
    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallBack(const ConnectionCallBack& cb)
        {
            _conn_cb = cb;
        }
        virtual void setMessageCallBack(const MessageCallBack& cb)
        {
            _msg_cb = cb;
        }
        virtual void setCloseCallBack(const CloseCallBack& cb)
        {
            _close_cb = cb;
        }
        // 连接服务端函数
        virtual void connect() = 0;
        // 发送消息函数
        virtual bool send(const BaseMessage::ptr& msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
        // 获取连接对象
        virtual BaseConnection::ptr connection() = 0;
    protected:
        ConnectionCallBack _conn_cb;
        MessageCallBack _msg_cb;
        CloseCallBack _close_cb;
    };
}